package com.bayss.core.service;

import com.bayss.core.DokoServerException;
import com.bayss.core.DokoServerExceptionFactor;
import com.bayss.core.entity.classify.Classify;
import com.bayss.core.entity.classify.ClassifyItem;
import com.bayss.core.entity.foodBox.FoodBox;
import com.bayss.core.entity.goods.*;
import com.bayss.core.entity.goods.mapper.ListClassifyMapper;
import com.bayss.core.entity.goods.mapper.SkuMapper;
import com.bayss.core.entity.goods.mapper.SpuMapper;
import com.bayss.core.enums.ClassifyType;
import com.bayss.core.enums.GoodsType;
import com.bayss.core.model.SkuCost;
import com.bayss.core.model.SpuSkuInfo;
import com.bayss.core.service.code.CodeBaseService;
import com.bayss.core.service.food.FoodBoxService;
import com.bayss.core.util.BigDecimalUtil;
import com.bayss.core.util.CollectionUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author pangxin1
 * @date 2019-11-10 13:17
 */
@Service
public class GoodsService {

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private SpuMapper spuMapper;

    @Autowired
    private ListClassifyMapper listClassifyMapper;

    @Autowired
    private CodeBaseService codeBaseService;

    @Autowired
    private ClassifyService classifyService;

    @Autowired
    private FoodBoxService foodBoxService;

    private Map<String, Long> warnSkuMap = Maps.newConcurrentMap();

    /**
     * 查询所有分类
     *
     * @return
     */
    public List<ListClassify> findListClassify() {
        ListClassifyExample listClassifyExample = new ListClassifyExample();
        ListClassifyExample.Criteria criteria = listClassifyExample.createCriteria();
        criteria.andClassifyCodeIsNotNull();
        List<ListClassify> listClassifies = listClassifyMapper.selectByExample(listClassifyExample);
        return listClassifies;
    }

    /**
     * 获得所有code
     *
     * @param skus
     * @return
     */
    private List<String> getSkuCodes(List<Sku> skus) {
        List<String> list = Lists.newArrayList();
        for (Sku sku : skus) {
            list.add(sku.getSkuCode());
        }
        return list;
    }


    /**
     * 通过classifyCode 查找 spu 和 sku
     *
     * @param classifyCode
     * @return
     */
    public List<SpuSkuInfo> findGoodsByClassifyCode(Long classifyCode) {
        SpuExample spuExample = new SpuExample();
        SpuExample.Criteria criteria = spuExample.createCriteria();
        criteria.andClassifyIdEqualTo(classifyCode);
        criteria.andSpuCodeNotEqualTo("self_spu_");//过滤自选餐
        List<Spu> spus = spuMapper.selectByExample(spuExample);
        if (CollectionUtils.isEmpty(spus)) {
            return Lists.newCopyOnWriteArrayList();
        }
        List<SpuSkuInfo> spuSkuInfos = Lists.newCopyOnWriteArrayList();
        spus.parallelStream()
                .forEach(spu -> {
                    SkuExample skuExample = new SkuExample();
                    SkuExample.Criteria skuExampleCriteria = skuExample.createCriteria();
                    skuExampleCriteria.andSpuCodeEqualTo(spu.getSpuCode());

                    List<Sku> skus = skuMapper.selectByExample(skuExample);
                    if (CollectionUtils.isEmpty(skus)) {
                        return;
                    }
                    Sku sku = skus.get(0);
                    if (skus.size() > 1) {
                        //添加spu
                        SpuSkuInfo build = SpuSkuInfo.builder()
                                .classifyId(spu.getClassifyId())
                                .descCn(spu.getSpuDescCn())
                                .descEn(spu.getSpuDescEn())
                                .descKo(spu.getSpuDescKo())
                                .goodsType(GoodsType.spu)
                                .imageCn(spu.getSpuImageCn())
                                .imageEn(spu.getSpuImageEn())
                                .imageKo(spu.getSpuImageKo())
                                .nameCn(spu.getSpuNameCn())
                                .nameEn(spu.getSpuNameEn())
                                .nameKo(spu.getSpuNameKo())
                                .id(spu.getId())
                                .salesMonth(spu.getSalesMonth() + spu.getSalesMonthInjection())
                                .price(sku.getPrice())
                                .spec(classifyService.findSpec(spu.getSpuCode()))
                                .skuCodes(getSkuCodes(skus))
                                .defaultSkuCode(sku.getSkuCode())
                                .inventory(sku.getInventory())
                                .build();
                        spuSkuInfos.add(build);

                    } else {
                        //添加sku
                        SpuSkuInfo build = SpuSkuInfo.builder()
                                .classifyId(spu.getClassifyId())
                                .descCn(sku.getSkuDescCn())
                                .descEn(sku.getSkuDescEn())
                                .descKo(sku.getSkuDescKo())
                                .goodsType(GoodsType.sku)
                                .imageCn(sku.getSkuImageCn())
                                .imageEn(sku.getSkuImageEn())
                                .imageKo(sku.getSkuImageKo())
                                .nameCn(sku.getSkuNameCn())
                                .nameEn(sku.getSkuNameEn())
                                .nameKo(sku.getSkuNameKo())
                                .id(sku.getId().intValue())
                                .salesMonth(sku.getSalesMonth() + sku.getSalesMonthInjection())
                                .price(sku.getPrice())
                                .spec(classifyService.findSpec(spu.getSpuCode()))
                                .skuCodes(getSkuCodes(skus))
                                .defaultSkuCode(sku.getSkuCode())
                                .inventory(sku.getInventory())
                                .build();
                        spuSkuInfos.add(build);

                    }
                });

        return spuSkuInfos;
    }


    /**
     * 查询sku详情
     *
     * @param skuCode
     * @return
     */
    public Sku getSkuDesc(String skuCode) {

        //自选餐
        if (skuCode.contains("self_sku_")) {
            return getSelfSkuDescByCheck(skuCode, true);
        } else {
            return getBaseSku(skuCode);
        }

//
//        SkuExample skuExample = new SkuExample();
//        SkuExample.Criteria skuExampleCriteria = skuExample.createCriteria();
//        skuExampleCriteria.andSkuCodeEqualTo(skuCode);
//        List<Sku> skus = skuMapper.selectByExample(skuExample);
//        if (CollectionUtils.isNotEmpty(skus)) {
//            Sku sku = skus.get(0);
//            skuExample.clear();
//            SkuExample.Criteria criteria = skuExample.createCriteria();
//            criteria.andSpuCodeEqualTo(sku.getSpuCode());
//            List<Sku> allSkus = skuMapper.selectByExample(skuExample);
//            FoodBox foodBox = foodBoxService.getFoodBox(sku.getFoodBoxId());
//            sku.setFoodBox(foodBox);
//            sku.setSpec(classifyService.findSpec(sku.getSpuCode()));
//            sku.setSkuCodes(getSkuCodes(allSkus));
//            sku.setSalesMonth(sku.getSalesMonth() + sku.getSalesMonthInjection());
//            return sku;
//        }
    }

    private Sku getBaseSku(String skuCode) {
        SkuExample skuExample = new SkuExample();
        SkuExample.Criteria skuExampleCriteria = skuExample.createCriteria();
        skuExampleCriteria.andSkuCodeEqualTo(skuCode);
        List<Sku> skus = skuMapper.selectByExample(skuExample);
        if (CollectionUtils.isNotEmpty(skus)) {
            Sku sku = skus.get(0);
            skuExample.clear();
            SkuExample.Criteria criteria = skuExample.createCriteria();
            criteria.andSpuCodeEqualTo(sku.getSpuCode());
            List<Sku> allSkus = skuMapper.selectByExample(skuExample);
            FoodBox foodBox = foodBoxService.getFoodBox(sku.getFoodBoxId());
            sku.setFoodBox(foodBox);
            sku.setSpec(classifyService.findSpec(sku.getSpuCode()));
            sku.setSkuCodes(getSkuCodes(allSkus));
            sku.setSalesMonth(sku.getSalesMonth() + sku.getSalesMonthInjection());
            return sku;
        }
        return null;
    }

    /**
     * 获得自选餐配置规则
     *
     * @return
     */
    public Map<String, String> getSelfSkuRule() {
        String selfSkuRule = codeBaseService.getCodeValueByCode("self_sku_rule");
        if (!StringUtils.isEmpty(selfSkuRule)) {
            String[] item = selfSkuRule.split("_");
            Map<String, String> rule = Maps.newConcurrentMap();
            for (String one : item) {
                String[] kv = one.split("\\*");
                rule.put(kv[0], kv[1]);
            }
            return rule;

        }
        return Maps.newHashMap();
    }

//    @PostConstruct
//    public void test() {
//        checkSkuExist("sku_1584456579224_6L6j_5bCP5Lu9_5p6c5rGB");
//    }

    /**
     * 校验sku 是否存在
     * true 存在
     * false 不存在
     *
     * @param skuCode
     * @return
     */
    public boolean checkSkuExist(String skuCode) {
        if (skuCode.contains("self_sku_")) {
            String selfSkuCode = skuCode.replace("self_sku_", "");
            if (selfSkuCode.contains("1") &&
                    selfSkuCode.contains("2") &&
                    selfSkuCode.contains("3") &&
                    selfSkuCode.contains("4") &&
                    selfSkuCode.contains("5") &&
                    selfSkuCode.contains("6")) {
                return true;

            }
            return false;
        } else {
            SkuExample skuExample = new SkuExample();
            SkuExample.Criteria skuExampleCriteria = skuExample.createCriteria();
            skuExampleCriteria.andSkuCodeEqualTo(skuCode);
            List<Sku> skus = skuMapper.selectByExample(skuExample);
            if (CollectionUtils.isEmpty(skus)) {
                return false;
            }
            return true;
        }
    }

    /**
     * 自选餐校验规则
     * 1*1_2*1_3*4_4*1_5*1
     *
     * @param skuCode
     */
    public void checkSelfSku(String skuCode) {
        Map<String, String> selfSkuRule = getSelfSkuRule();
        Map<String, List<Item>> selfSkuItem = getSelfSkuItem(skuCode);
        //如果自选餐校验
        if (selfSkuItem == null) {
            return;
        }
        for (String key : selfSkuItem.keySet()) {
            List<Item> items = selfSkuItem.get(key);
            String count = selfSkuRule.get(key);

            int countTemp = 0;
            for (Item item : items) {
                countTemp += item.getCount();
            }
            //如果是超过第五步直接过滤掉
            if (Integer.valueOf(key) > 5) {
                continue;
            }

            if (Integer.valueOf(count) < countTemp) {
                throw new DokoServerException(DokoServerExceptionFactor.SELF_SKU_COUNT_ERROR, "step " + key + " must be select less than " + count);
            }

        }
    }

    /**
     * 自选skuDesc
     * <p>
     * self_sku_1:code*1_2:code_3:code_4:code_5:code_6:code-code-code
     *
     * @param skuCode
     * @return
     */
    public Sku getSelfSkuDesc(String skuCode) {
        return getSelfSkuDescByCheck(skuCode, false);
    }

    /**
     * 计算自选餐第六步价格
     * self_sku_1:code*1_2:code_3:code_4:code_5:code_6:code-code-code
     *
     * @param skuCode
     * @return
     */
    public Integer getSelfSkuStep6Price(String skuCode) {
        String selfSkuCode = skuCode.replace("self_sku_", "");
        if (StringUtils.isEmpty(selfSkuCode)) {
            return 0;
        }
        String[] steps = selfSkuCode.split("_");
        for (String step : steps) {
            if (step.contains("6:")) {
                String replace = step.replace("6:", "");
                if (StringUtils.isEmpty(replace)) {
                    return 0;
                }
                String[] codes = replace.split("-");
                Integer totalPrice = 0;
                for (String code : codes) {
                    if (StringUtils.isEmpty(code)) {
                        continue;
                    }
                    String[] split = code.split("\\*");
                    ClassifyItem classifyItemByCode = classifyService.findClassifyItemByCode(split[0]);

                    if (classifyItemByCode == null) {
                        throw new DokoServerException(DokoServerExceptionFactor.SELF_SKU_CLASSIFY_ITEM_MISS, "自选餐类目丢失，请重新进入");
                    }

                    Integer price = BigDecimalUtil.mul(classifyItemByCode.getPrice(), Integer.valueOf(split[1]));
                    totalPrice += price;
                }
                return totalPrice;
            }
        }
        return 0;
    }

    /**
     * 自选skuDesc
     * TODO 拼装本实体
     * <p>
     * self_sku_1:code*1-code*1_2:code_3:code_4:code_5:code_6:code-code-code
     *
     * @param skuCode
     * @return
     */
    public Sku getSelfSkuDescByCheck(String skuCode, boolean check) {

        if (check) {
            checkSelfSku(skuCode);
        }
        Map<String, List<Item>> selfSkuItem = getSelfSkuItem(skuCode);
        Sku sku = getBaseSku("self_sku_");
        sku.setSelfItem(selfSkuItem);
        sku.setFoodBox(foodBoxService.getFoodBox(sku.getFoodBoxId()));
        return sku;
    }

    public Map<String, List<Item>> getSelfSkuItem(String skuCode) {

        String selfSkuCode = skuCode.replace("self_sku_", "");
        if (StringUtils.isEmpty(selfSkuCode)) {
            return null;
        }
        Map<String, List<Item>> selfSkuItem = Maps.newConcurrentMap();
        String[] steps = selfSkuCode.split("_");
        for (String oneStem : steps) {
            String[] codes = oneStem.split(":");
            //第几步
            String bu = codes[0];
            //下面就得判断是否存在的情况。
            if (codes.length > 1) {
                //所有的code
                String allCode = codes[1];
                //多个情况
                String[] codeAndCount = allCode.split("-");
                List<Item> list = Lists.newArrayList();
                for (String oneCodeAndCount : codeAndCount) {
                    String[] oneCodeAndCountSplit = oneCodeAndCount.split("\\*");
                    String code = oneCodeAndCountSplit[0];
                    int countInt = 1;
                    if (oneCodeAndCountSplit.length > 1) {
                        String count = oneCodeAndCountSplit[1];
                        countInt = Integer.parseInt(count);
                    }
                    Item item = new Item();
                    item.setCode(code);
                    item.setCount(countInt);
                    item.setName(classifyService.findClassifyItemByCode(code).getItemNameCn());
                    list.add(item);
                }

                selfSkuItem.put(bu, list);
            }

        }
        return selfSkuItem;
    }


    /**
     * 获得自选餐所有配料
     *
     * @return
     */
    public List<Classify> getIngredient() {
        return classifyService.findClassifyAndClassifyItemByType(ClassifyType.INGREDIENTS.getType());
    }


    /**
     * 计算价格
     *
     * @param skuMaps
     */
    public SkuCost cost(Map<String, Integer> skuMaps) {

        //正常餐品
        List<String> skuCodes = Lists.newArrayList();
        skuCodes.addAll(skuMaps.keySet().stream().filter(item -> !item.contains("self_sku_")).collect(Collectors.toList()));

        //自选餐品
        List<String> selfSku = Lists.newArrayList();
        selfSku.addAll(skuMaps.keySet().stream().filter(item -> item.contains("self_sku_")).collect(Collectors.toList()));

        //总量计算价格
        int skuTotalPrice = 0;
        int boxTotalPrice = 0;
        Map<String, Integer> skuPriceMap = new HashMap<>();
        Map<String, Integer> boxPriceMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(skuCodes)) {
            SkuExample skuExample = new SkuExample();
            SkuExample.Criteria skuExampleCriteria = skuExample.createCriteria();
            skuExampleCriteria.andSkuCodeIn(skuCodes);
            List<Sku> skus = skuMapper.selectByExample(skuExample);

            for (Sku sku : skus) {
                int skuPrice = BigDecimalUtil.mul(sku.getPrice(), skuMaps.get(sku.getSkuCode()));
                skuPriceMap.put(sku.getSkuCode(), skuPrice);
                skuTotalPrice += skuPrice;
                FoodBox foodBox = foodBoxService.getFoodBox(sku.getFoodBoxId());
                int boxPrice = 0;
                if (foodBox != null) {
                    boxPrice = BigDecimalUtil.mul(foodBox.getBoxPrice(), skuMaps.get(sku.getSkuCode()));
                    boxTotalPrice += boxPrice;
                }
                boxPriceMap.put(sku.getSkuCode(), boxPrice);
            }
        }

        //计算自选餐的费用
        if (CollectionUtils.isNotEmpty(selfSku)) {
            for (String oneSelfSku : selfSku) {
                Sku selfSkuDesc = getSelfSkuDesc(oneSelfSku);
                Integer price = selfSkuDesc.getPrice();
                Integer selfSkuStep6Price = getSelfSkuStep6Price(oneSelfSku);
                price += selfSkuStep6Price;
                int skuPrice = BigDecimalUtil.mul(price, skuMaps.get(oneSelfSku));
                skuPriceMap.put(oneSelfSku, skuPrice);
                skuTotalPrice += skuPrice;
                int boxPrice = BigDecimalUtil.mul(selfSkuDesc.getFoodBox().getBoxPrice(), skuMaps.get(oneSelfSku));
                boxTotalPrice += boxPrice;
                boxPriceMap.put(oneSelfSku, boxPrice);
            }
        }

        return SkuCost.builder()
                .totalBoxPrice(boxTotalPrice)
                .totalPrice(skuTotalPrice + boxTotalPrice)
                .totalSkuPrice(skuTotalPrice)
                .skuPriceMaps(skuPriceMap)
                .boxPriceMaps(boxPriceMap)
                .build();
    }


    /**
     * 检查库存是否够用
     *
     * @param skuMaps
     */
    private void checkInventory(Map<String, Integer> skuMaps) {

        for (Map.Entry<String, Integer> skuMap : skuMaps.entrySet()) {
            String skuCode = skuMap.getKey();
            Integer value = skuMap.getValue();
            if (skuCode.contains("self_sku_")) {
                Sku selfSkuDesc = getSelfSkuDesc(skuCode);
                if (selfSkuDesc.getInventory() < value) {
                    throw new DokoServerException(DokoServerExceptionFactor.SKU_INVENTORY_COUNT_ERROR, selfSkuDesc.getSkuNameCn());
                }

            } else {
                SkuExample skuExample = new SkuExample();
                SkuExample.Criteria skuExampleCriteria = skuExample.createCriteria();
                skuExampleCriteria.andSkuCodeEqualTo(skuCode);
                List<Sku> skus = skuMapper.selectByExample(skuExample);
                if (CollectionUtils.isEmpty(skus)) {
                    throw new DokoServerException(DokoServerExceptionFactor.SKU_INVENTORY_COUNT_ERROR, "sku 不存在");
                }
                Sku sku = skus.get(0);
                if (sku.getInventory() < value) {
                    throw new DokoServerException(DokoServerExceptionFactor.SKU_INVENTORY_COUNT_ERROR, sku.getSkuNameCn());
                }
            }
        }
    }

    /**
     * 减少库存
     *
     * @param skuMaps
     */
    public synchronized Map<String, Boolean> reduce(Map<String, Integer> skuMaps) {
        checkInventory(skuMaps);
        //正常餐品
        Map<String, Boolean> result = Maps.newConcurrentMap();
        for (Map.Entry<String, Integer> skuMap : skuMaps.entrySet()) {
            String skuCode = skuMap.getKey();
            Integer value = skuMap.getValue();

            if (skuCode.contains("self_sku_")) {
                //自选餐库存
                Sku selfSkuDesc = getSelfSkuDesc(skuCode);
                String selfSkuDbCode = "self_sku_";
                checkInventoryAlarm(selfSkuDesc);
                int updateFlag = skuMapper.updateSkuInventory(selfSkuDbCode, value);
                result.put(skuCode, updateFlag > 0);
            } else {
                SkuExample skuExample = new SkuExample();
                SkuExample.Criteria skuExampleCriteria = skuExample.createCriteria();
                skuExampleCriteria.andSkuCodeEqualTo(skuCode);
                List<Sku> skus = skuMapper.selectByExample(skuExample);
                if (CollectionUtils.isEmpty(skus)) {
                    result.put(skuCode, false);
                    continue;
                }
                Sku sku = skus.get(0);
                checkInventoryAlarm(sku);
                int updateFlag = skuMapper.updateSkuInventory(skuCode, value);
                result.put(skuCode, updateFlag > 0);
            }
        }
        return result;

    }

    /**
     * 库存回滚
     *
     * @param skus
     * @return
     */
    public synchronized Map<String, Boolean> rollBack(Map<String, Integer> skus) {
        for (Map.Entry<String, Integer> skuMaps : skus.entrySet()) {
            skus.put(skuMaps.getKey(), -skuMaps.getValue());
        }
        return reduce(skus);
    }


    /**
     * TODO 短信报警 接入短信通道
     * 检查库存是否报警
     *
     * @param sku
     * @return
     */
    public void checkInventoryAlarm(Sku sku) {
        if (sku.getInventory() < sku.getInventoryAlarmThreshold()) {
            //进行报警
            Long time = warnSkuMap.get(sku.getSkuCode());
            if (time == null) {
                warnSkuMap.put(sku.getSkuCode(), System.currentTimeMillis());
                // TODO 发送报警短信

            } else {
                if (System.currentTimeMillis() - time > 1000 * 60 * 60) {
                    warnSkuMap.put(sku.getSkuCode(), System.currentTimeMillis());
                    // TODO 发送报警短信

                }
            }
        }
    }

}
